package com.tinyengine.it.controller.db;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tinyengine.it.common.base.Result;
import com.tinyengine.it.common.utils.JavaClassNameValidator;
import com.tinyengine.it.common.utils.JavaDataType;
import com.tinyengine.it.model.entity.DbLogicalFieldsInfo;
import com.tinyengine.it.model.entity.DbLogicalInfo;
import com.tinyengine.it.model.entity.DbTableFieldsInfo;
import com.tinyengine.it.model.vo.DbLogicalFieldsInfoVo;
import com.tinyengine.it.model.vo.DbLogicalInfoVo;
import com.tinyengine.it.model.vo.DbLogicalSimpleVo;
import com.tinyengine.it.service.db.DbLogicalFieldsInfoService;
import com.tinyengine.it.service.db.DbLogicalInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

@RestController
@RequestMapping("/table-logical/api")
@Tag(name = "数据库逻辑实体字段维护")
@Validated
@RequiredArgsConstructor
public class DbTableLogicalInfoController {

    private final DbLogicalFieldsInfoService dbLogicalFieldsInfoService;
    private final DbLogicalInfoService dbLogicalInfoService;

    @Operation(summary = "根据服务ID获取逻辑实体列表-下拉(不带ID默认所有)",
            parameters = {
                    @Parameter(name = "serviceId", description = "服务ID")
            },
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = DbLogicalSimpleVo.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @GetMapping("/getLogicalList")
    public Result<List<DbLogicalSimpleVo>> getLogicalList(@RequestParam(value = "serviceId") Integer serviceId, @RequestHeader(required = false) Integer appId) {
        LambdaQueryWrapper<DbLogicalInfo> queryWrapper = new LambdaQueryWrapper<>();
        if (ObjUtil.isNotNull(serviceId)) {
            queryWrapper.eq(DbLogicalInfo::getServiceId, serviceId);
        }
        if (ObjUtil.isNotNull(appId)) {
            queryWrapper.eq(DbLogicalInfo::getAppId, appId);
        }
        List<DbLogicalInfo> list = dbLogicalInfoService.list(queryWrapper);
        return Result.success(BeanUtil.copyToList(list, DbLogicalSimpleVo.class));
    }

    @Operation(summary = "跟表ID获取字段列表",
            parameters = {
                    @Parameter(name = "tableId", description = "表ID")
            },
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = DbTableFieldsInfo.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @GetMapping("/getFieldsInfoByTableId")
    public Result<List<DbLogicalFieldsInfoVo>> getFieldsInfoByTableId(@RequestParam("tableId") Integer tableId) {
        List<DbLogicalFieldsInfo> list = dbLogicalFieldsInfoService.list(Wrappers.<DbLogicalFieldsInfo>lambdaQuery().eq(DbLogicalFieldsInfo::getTableId, tableId));
        return Result.success(BeanUtil.copyToList(list, DbLogicalFieldsInfoVo.class));
    }


    //@Operation(summary = "新增及更新实体字段",
    //        responses = {@ApiResponse(responseCode = "200", description = "返回信息",
    //                content = @Content(mediaType = "application/json",
    //                        schema = @Schema(implementation = Result.class))),
    //                @ApiResponse(responseCode = "400", description = "请求失败")}
    //)
    //@PostMapping("/addAndUpdateFields")
    //public Result addAndUpdateFields(@RequestBody @Validated DbLogicalFieldsInfoVo dbLogicalFieldsInfoVo) {
    //    DbLogicalFieldsInfo dbLogicalFieldsInfo = BeanUtil.copyProperties(dbLogicalFieldsInfoVo, DbLogicalFieldsInfo.class);
    //    dbLogicalFieldsInfoService.saveOrUpdate(dbLogicalFieldsInfo);
    //    return Result.success(dbLogicalFieldsInfo.getId());
    //}


    @Operation(summary = "新增及更新包含逻辑实体",
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @PostMapping("/addAndUpdate")
    public Result addAndUpdate(@RequestBody @Validated DbLogicalInfoVo dbLogicalInfoVo, @RequestHeader(required = false) Integer appId) {
        LambdaQueryWrapper<DbLogicalInfo> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.eq(DbLogicalInfo::getCode, dbLogicalInfoVo.getCode()).last("limit 1");
        if (ObjUtil.isNotNull(appId)) {
            lambdaQuery.eq(DbLogicalInfo::getAppId, appId);
        }
        DbLogicalInfo isExist = dbLogicalInfoService.getOne(lambdaQuery);

        if (ObjUtil.isNull(dbLogicalInfoVo.getId()) && ObjUtil.isNotNull(isExist)) {
            throw new RuntimeException("实体Code已经存在，请修改!");
        }

        String validClassName = JavaClassNameValidator.isValidClassName(dbLogicalInfoVo.getCode());
        if (StrUtil.isNotBlank(validClassName)) {
            throw new RuntimeException(validClassName);
        }

        List<DbLogicalFieldsInfoVo> logicalFieldsInfoVo = dbLogicalInfoVo.getLogicalFieldsInfoVo();
        DbLogicalFieldsInfoVo isShipVo = logicalFieldsInfoVo.stream().filter(f -> StrUtil.isNotBlank(f.getDataType())
                && f.getDataType().toUpperCase().contains(JavaDataType.Object.getValue())
                && ObjUtil.isNull(f.getShipVoId())
        ).findFirst().orElse(null);
        if (ObjUtil.isNotNull(isShipVo)) {
            throw new RuntimeException("选择object对象，但未做关联，请修改!");
        }
        dbLogicalInfoVo.setAppId(appId);
        DbLogicalInfoVo logicalInfoVo = dbLogicalInfoService.saveInfo(dbLogicalInfoVo);

        return Result.success(logicalInfoVo);
    }


    @Operation(summary = "根据ID删除表",
            parameters = {
                    @Parameter(name = "id", description = "ID")},
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @GetMapping("/deleteById/{id}")
    public Result deleteProjectServiceGroupInf1o(@Valid @PathVariable Integer id) {
        dbLogicalFieldsInfoService.removeById(id);
        return Result.success();
    }


    @Operation(summary = "根据逻辑表ID删除，包含下面所有字段",
            parameters = {
                    @Parameter(name = "id", description = "ID")},
            responses = {@ApiResponse(responseCode = "200", description = "返回信息",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))),
                    @ApiResponse(responseCode = "400", description = "请求失败")}
    )
    @GetMapping("/deleteAllById/{id}")
    public Result deleteAllById(@Valid @PathVariable Integer id) {
        dbLogicalInfoService.removeById(id);
        dbLogicalFieldsInfoService.remove(Wrappers.<DbLogicalFieldsInfo>lambdaQuery().eq(DbLogicalFieldsInfo::getTableId, id));
        return Result.success();
    }
}
